package ru.compft.common.dao.impl;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import ru.compft.common.dao.AclDao;
import ru.compft.common.data.acl.AclClass;
import ru.compft.common.data.acl.AclEntry;
import ru.compft.common.data.acl.AclObjectIdentity;
import ru.compft.common.data.meta.acl.AclClassProperty;
import ru.compft.common.data.meta.acl.AclEntryProperty;
import ru.compft.common.data.meta.acl.AclObjectIdentityProperty;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: VVasiliev
 * Date: 24.09.12
 * Time: 13:44
 * DAO работы с ACL таблицами
 */
@Repository
public class AclDaoImpl implements AclDao {
    private static final Logger logger = LoggerFactory.getLogger(AclDaoImpl.class);

    @Resource(name = "sessionFactory")
    private SessionFactory sessionFactory;

    @Override
    public List<AclEntry> getAllAclEntries() {
        Session session = sessionFactory.getCurrentSession();
        Criteria criteria = session.createCriteria(AclEntry.class);

        return criteria.list();
    }

    /**
     * Получаем все ACL Entry записи для данного класса
     *
     * @param className
     * @return
     */
    @Override
    public List<AclEntry> getAllAclEntriesByClassName(String className) {
        final List<AclObjectIdentity> objectIdentityList = getAclObjectIdentityByClassName(className);

        if (!CollectionUtils.isEmpty(objectIdentityList)) {
            final List<AclEntry> resultList = new ArrayList<AclEntry>();

            for (AclObjectIdentity objectIdentity : objectIdentityList) {
                final List<AclEntry> entryList = getAclEntryForObjectIdentity(objectIdentity.getId());
                resultList.addAll(entryList);
            }

            return resultList;
        }
        return null;
    }

    @Override
    public List<AclObjectIdentity> getAclObjectIdentityByClassName(String className) {
        final Long aclClassId = getAclClassIdByName(className);

        if (aclClassId != null) {
            Session session = sessionFactory.getCurrentSession();
            Criteria criteria = session.createCriteria(AclObjectIdentity.class)
                    .add(Restrictions.eq(AclObjectIdentityProperty.objectIdClass, aclClassId));

            return criteria.list();
        }
        return null;
    }

    private List<AclEntry> getAclEntryForObjectIdentity(Long objectIdentityId) {
        Session session = sessionFactory.getCurrentSession();
        Criteria criteria = session.createCriteria(AclEntry.class)
                .add(Restrictions.eq(AclEntryProperty.aclObjectIdentity, objectIdentityId));

        return criteria.list();
    }

    /**
     * Получаем ID класса по его названию
     *
     * @param className
     * @return
     */
    private Long getAclClassIdByName(String className) {
        Session session = sessionFactory.getCurrentSession();
        Criteria criteria = session.createCriteria(AclClass.class)
                .add(Restrictions.like(AclClassProperty.aclClass, className));

        final AclClass aclClass = (AclClass) criteria.uniqueResult();
        return aclClass != null ? aclClass.getId() : null;
    }
}
